/*****************************************************
 *
 * scHelper.js
 *****************************************************/
sc.Helper = {};


sc.Helper.seekWidgetByName =  function (root, name) {
    if (!root)
        return null;
    if (root.getName() === name)
        return root;
    var arrayRootChildren = root.getChildren();
    var length = arrayRootChildren.length;
    for (var i = 0; i < length; i++) {
        var child = arrayRootChildren[i];
        var res = sc.Helper.seekWidgetByName(child, name);
        if (res !== null)
            return res;
    }
    return null;
};

sc.Helper.seekWidgetByTag = function (root, tag) {
    if (!root)
        return null;
    if (root.getTag() === tag)
        return root;

    var arrayRootChildren = root.getChildren();
    var length = arrayRootChildren.length;
    for (var i = 0; i < length; i++) {
        var child = arrayRootChildren[i];
        var res = sc.Helper.seekWidgetByTag(child, tag);
        if (res !== null)
            return res;
    }
    return null;
};

sc.Helper.seekActionWidgetByActionTag = function (root, tag) {
    if (!root)
        return null;
    if (root.getActionTag() === tag)
        return root;
    var arrayRootChildren = root.getChildren();
    for (var i = 0; i < arrayRootChildren.length; i++) {
        var child = arrayRootChildren[i];
        var res = sc.Helper.seekActionWidgetByActionTag(child, tag);
        if (res !== null)
            return res;
    }
    return null;
};

sc.Helper.setFrameEventCallFunc = function (action, func, node) {
    action.setFrameEventCallFunc(function (frame) {
        func (frame, node);
    });
};

sc.Helper.setFrameEvent = function (action, hash, node) {
    action.setFrameEventCallFunc(function (frame) {
        var strEvent = frame.getEvent();
        for (var v in hash)
        {
            if (v === strEvent) hash[v] (frame, node);
        }
    });
};

/*****************************************************
 * 游戏退出时的事件列表
 *****************************************************/

sc.Helper.quitList = [];
sc.Helper.gameQuit = function () {
    var list = sc.Helper.quitList;
    for (var i in list)
    {
        if (list[i]) list[i] ();
    }
    cc.director.end();
};

/*****************************************************
 * 坐标转换
 *****************************************************/

sc.Transform = cc.Class.extend ({
    Node:null,
    ctor: function (node) {
        this.Node = node;
    },
    init: function (node) {
        this.Node = node;
    },
    position: function () {
        var p = this.Node.getParent ();
        return p.convertToWorldSpace(this.Node.getPosition ());
    },
    setPosition: function (position) {
        var p = this.Node.getParent();
        this.Node.setPosition(p.convertToNodeSpace(position));
    },
    InverseTransformPoint: function (position) {
        var p = this.Node.getParent();
        return (p.convertToNodeSpace(position));
    },
    localPosition: function () {
        return (cc.pSub(this.Node.getPosition() - this.Node.getParent().getPosition()));
    },
    setLocalPosition: function (m_pPosition) {
        var p = this.Node.getParent().getPosition();
        this.Node.setPosition(cc.pAdd(p, m_pPosition));
    },
    rotation: function () {
        return this.Node.getRotation();
    }
});
sc.Transform.WorldToNodePoint = function (Node) {
    var p = Node.getParent();
    return (p.convertToWorldSpace(Node.getPosition()));
};
sc.Transform.NodeToWorldPoint = function (Node,position) {
    var p = Node.getParent();
    Node.setPosition(p.convertToNodeSpace(position));
}

/*****************************************************
 * 发送一个协程去update,直到结束
 *****************************************************/
sc.Coroutine = cc.Class.extend ({
    event:[],
    update: function (dt) {
        var list = [];
        var events = this.event;
        if (events != null && events.length > 0) {
            for (var i= 0, L = events.length; i < L; ++i) {
                var e = events[i];
                e.update (dt);
                if (!e.isComplete ()) {
                    list.push (e);
                }
            }
        }
        this.event = list;
    },
    addEvent: function (monitor) {
        this.event.push (monitor);
    }
});

sc.Monitor = cc.Class.extend ({
    userData:null,
    complete:false,
    update:null,
    ctor: function (func) {
        this.update = func;
    },
    init: function (func) {
        this.update = func;
    },
    isComplete: function () {
        return this.complete;
    },
    Close: function () {
        this.complete = true;
    }
});

/*****************************************************
 *  画屏幕参考框
 *****************************************************/
sc.Debug =
{
    drawNodeRender:null,

    drawVisiableRect: function (node) {
        if (!this.isDebug ()) {
            return;
        }
        this.drawNodeRender = new cc.DrawNode();
        node.addChild( this.drawNodeRender, 100);
        this.drawNodeRender .clear();
        var drawCenter = sc.World.centerPoint;
        var dw = 540;//854;
        var dh = 850;//518;
        if (sc.World.winSize.width > sc.World.winSize.height) {
            dw = 854;
            dh = 518;
        }
        var leftup =    cc.pAdd(drawCenter, cc.p (-dw * 0.5, dh *0.5));
        var rightup =   cc.pAdd(drawCenter, cc.p ( dw * 0.5, dh *0.5));
        var leftdown =  cc.pAdd(drawCenter, cc.p (-dw * 0.5,-dh *0.5));
        var rightdown = cc.pAdd(drawCenter, cc.p ( dw * 0.5,-dh *0.5));
        this.drawLine(leftup,   leftdown , 1, new cc.Color(127,255,212,255));
        this.drawLine(leftup,   rightup  , 1, new cc.Color(127,255,212,255));
        this.drawLine(rightup,  rightdown, 1, new cc.Color(127,255,212,255));
        this.drawLine(leftdown, rightdown, 1, new cc.Color(127,255,212,255));
    },

    isDebug: function () {
        return cc.game.config[cc.game.CONFIG_KEY.showFPS];
    },
    
    drawLine: function (a, b, r, color) {
        if (!this.isDebug ()) {
            return;
        }
        if (!color)
            color = new cc.Color(255,0,0,255)
        this.drawNodeRender.drawSegment(a,b,r,color);
    }
};

sc.Log = function (str) {
    if (sc.Debug.isDebug()) {
        console.log (str);
    }
};
/*****************************************************
 * 动画控制状态
 *****************************************************/
sc.Animator = cc.Class.extend ({
    anim:null,
    userData:null,

    ctor: function (anim) {
        this.anim = anim;
    },

    init: function (anim) {
        this.anim = anim;
    },

    preAnimName:null,
    preAnimPlay:false,
    curAnimPlay:false,
    onFinishAnim: function (name) {},

    update: function (dt) {
        if (this.anim == null) return;
        this.preAnimPlay = this.curAnimPlay;
        this.curAnimPlay =  this.anim.action.isPlaying();
        if (this.preAnimPlay && !this.curAnimPlay) {
            if (this.onFinishAnim != null)
                this.onFinishAnim (this.currentAnimName);
        }
    },

    //currentAnimName:"",
    //playAnim: function (animation, loop) {
    //    var action = this.anim.action;
    //    this.currentAnimName = animation.name;
    //    action.play(animation.name, loop);
    //    action.setTimeSpeed(animation.speed);
    //},
    getNode: function () {
        return this.anim.node;
    },

    getAction: function () {
        return this.anim.action;
    },

    currentAnimName:"",
    playAnim: function (animation, loop, whenAnimationComplete, target) {
        this.currentAnimName = animation.name;

        var action = this.anim.action;
        action.play(animation.name, loop);
        action.setTimeSpeed(animation.speed);

        if (whenAnimationComplete) {
            action.setLastFrameCallFunc(function () {
                if (!loop)
                    action.clearLastFrameCallFunc();

                if (target)
                    whenAnimationComplete.call (target);
                else
                    whenAnimationComplete ();
            });
        }
        else {
            action.clearLastFrameCallFunc();
        }

    },

    NoFinishCall:function () {
        this.onFinishAnim = null;
    },
    
    IsAnimName: function (animation) {
        return this.currentAnimName == animation.name;
    },
    
    IsPlaying: function () {
        return this.anim.action.isPlaying();
    }
});


/*****************************************************
 * 随机取数组中的一个
 *****************************************************/
sc.GetRandomOne = function (array) {
    var r = Math.floor(cc.rand()*10000)%array.length;
    var n = array[r];
    array.splice(r, 1);
    return {obj:n, no:r};
};


/*****************************************************
 * 复制数组
 *****************************************************/
sc.CopyArray = function (array) {
    var allNos = [];
    array.forEach(function (type) {
        allNos.push(type);
    });
    return allNos;
};


/*****************************************************
 * Vector2静态处理
 *****************************************************/
sc.Mathf = {

    //趋向点
    MoveTowardsPoint : function (current, target, maxDistanceDelta) {
        var vector 	= cc.pSub(target, current);
        var magnitude = cc.pLength(vector);
        if (magnitude > maxDistanceDelta &&
            magnitude != 0) {
            cc.pMult(vector, maxDistanceDelta/magnitude);
            cc.pAddIn(vector, current);
            return vector;
        }
        return target;
    },

    //趋向值
    MoveTowards: function (current, target, maxDistanceDelta) {
        var dir = target - current;
        var magnitude = Math.abs(dir);
        if (magnitude > maxDistanceDelta && magnitude != 0) {
            dir *= (maxDistanceDelta/magnitude);
            dir += current;
            return dir;
        }
        return target;
    },

    //趋向值,返回整形
    MoveTowardsInteger: function (current, target, delta) {
        if (current == target || delta == 0)
            return current;

        if (current < target) {
            current += delta;
            if (current >= target)
                return target;
            return Math.ceil(current);
        } else {
            current += delta;
            if (current <= target)
                return target;
            return Math.floor(current);
        }
    },

    //插值趋向,返回整形
    LerpInteger: function (current, target, delta) {
        if (Math.abs(current - target) < 1)
            return parseInt(target);
        current = current + (target - current) * delta;
        return (current <= target ? Math.ceil(current) : Math.floor(current));
    },

    RandomRange : function (min, max) {
        var L = max - min;
        return min + cc.random0To1() * L;
    },

    //围绕旋转
    RotateAround: function (node, position, angle) {
        var p = node.getPosition();
        var _p = cc.pRotateByAngle(p, position, angle);
        node.setPosition(_p);
    }
};

/*****************************************************
 * Skeletal动画
 *****************************************************/
sc.SkeletalAnimation = cc.Class.extend({
    anim: null,
    aniamtion: null,

    ctor: function (skeletalName) {
        this.init(skeletalName);
    },

    /**
     * @property{ccs.MovementEventType}
     start: 0,
     complete: 1,
     loopComplete: 2
     */
    init: function (skeletalName) {
        var anim = new ccs.Armature(skeletalName);
        this.anim = anim;
        this.animation = anim.getAnimation();
    },

    /**
     * function (bone, EventName, index, current) {}
     * */
    setFrameEventCallFunc: function (func, target) {
        this.animation.setFrameEventCallFunc(func, target);
    },

    /**
     * @property {ccs.Armature}
     * */
    getArmature: function () {
        return this.anim;
    },

    /**
     * @property {ccs.ArmatureAnimation}
     * */
    getAnimation: function () {
        return this.animation;
    },

    currentAnimName: "",
    playAnim: function (animation, durationTo, loop, whenAnimationComplete, target) {
        this.currentAnimName = animation.name;

        var anim = this.anim;
        anim.getAnimation().play(animation.name, durationTo, loop ? 1 : 0);
        anim.getAnimation().setSpeedScale(animation.speed);
        do
        {
            if (!whenAnimationComplete) {
                anim.getAnimation().setMovementEventCallFunc(null);
                break;
            }
            anim.getAnimation().setMovementEventCallFunc(function (animator, type, name) {
                if (type === ccs.MovementEventType.complete) {
                    if (target) whenAnimationComplete.call(target);
                    else whenAnimationComplete();
                } else if (type === ccs.MovementEventType.loopComplete) {
                    if (target) whenAnimationComplete.call(target);
                    else whenAnimationComplete();
                }
            });
        } while (false);
    },

    IsAnimName: function (animation) {
        return this.currentAnimName === animation.name;
    },

    SetSkin: function (boneName, texture, index) {
        //sc.Helper.seekWidgetByName(this.anim, boneName);
        var t = this.anim.getBone(boneName);
        if (t) {
            var skin = new ccs.Skin (texture, new cc.rect(0,0,0,0));
            t.addDisplay (skin, index);
            //t.changeDisplayWithIndex(index, true);
        }
    },

    ChangeDisplayWithIndex: function (boneName, index, force) {
        var t = this.anim.getBone(boneName);
        if (t) {
            t.changeDisplayWithIndex(index, force);
        }
    }
});


sc.SkeletalAnimation.addArmatureFileInfo = function (png, plist, xml) {
    ccs.armatureDataManager.addArmatureFileInfo(png, plist, xml);
};